/**
 * Copyright 2013-2015. blackdog1987@gmail.com . All rights reserved. 
 */
package com.gmail.blackdog1987.onedollar.dao.hibernate;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.gmail.blackdog1987.onedollar.util.DateUtil;

/**
 * @author DongGuoChao
 * @date 2013-12-26
 */
public class HibernateDaoGenerator {

	private static String DEFAULT_FILE_COMMENT = "/**\n * Copyright 2013-2015. blackdog1987@gmail.com "
			+ "All rights reserved.\n * \n */\n\n";

	private static String DEFAULT_TYPE_COMMENT = "/**\n *@author DongGuoChao HibernateDaoGenerator create "
			+ DateUtil.getToday() + "\n *\n */\n";

	private static String DEFAULT_DAO_SUFFIX = "Dao";
	private static String DEFAULT_BASE_DAO = "com.gmail.blackdog1987.onedollar.dao.hibernate.EntityHibernateDao";
	private static String DEFAULT_BASE_DAO_CLASS = "EntityHibernateDao";

	private boolean overWrite = false;
	private String fileComment = DEFAULT_FILE_COMMENT;
	private String typeComment = DEFAULT_TYPE_COMMENT;
	private List<String> pkgImports = new ArrayList<String>();
	private String sourcePath;
	private String sourcePackage;
	private String targetPackage;
	private String targetPath;
	private int subStart = 0;

	public HibernateDaoGenerator() {
	}

	public HibernateDaoGenerator(String sourcePath, String sourcePackage,
			String targetPath, String targetPackage) {
		this.sourcePath = sourcePath;
		this.sourcePackage = sourcePackage;
		this.targetPath = targetPath;
		this.targetPackage = targetPackage;

		targetPathCheck(targetPath);
	}

	public void generate() throws IOException {
		if (this.sourcePackage == null || this.sourcePath == null
				|| this.targetPackage == null || this.targetPath == null) {
			throw new NullPointerException(
					"The paramerts sourcePackage,sourcePath,targetPackage,targetPath must not be null.");
		}

		for (String className : getEntityClassNames(sourcePath)) {
			StringBuffer content = new StringBuffer();
			String fileName = className.substring(this.subStart,
					this.subStart + 1)
					+ className.substring(this.subStart + 1)
					+ DEFAULT_DAO_SUFFIX;
			content.append(fileComment);
			content.append("package " + targetPackage + ";\n\n");
			content.append("import " + DEFAULT_BASE_DAO + ";\n");
			content.append("import " + sourcePackage + "." + className
					+ ";\n\n");
			content.append(typeComment);
			content.append("public class " + fileName + " extends ");
			content
					.append(DEFAULT_BASE_DAO_CLASS + "<" + className
							+ ">{\n}\n");

			generateClass(fileName, content.toString());
		}
	}

	protected void targetPathCheck(String targetPath) {
		if (targetPath == null) {
			throw new NullPointerException(
					"The param targetPath must not be null.");
		}

		File file = new File(targetPath);
		file.mkdirs();
	}

	protected void generateClass(String fileName, String content)
			throws IOException {
		File file = new File(targetPath + fileName + ".java");
		if (!file.exists() || this.overWrite) {
			FileWriter writer = new FileWriter(file);
			try {
				writer.write(content);
			} finally {
				writer.close();
			}
		}
	}

	protected List<String> getEntityClassNames(String path) {
		List<String> list = new ArrayList<String>();
		File dir = new File(path);
		if (dir.isDirectory()) {
			File[] files = dir.listFiles();
			for (int i = 0; i < files.length; i++) {
				File file = files[i];
				if (!file.isDirectory()) {
					list.add(file.getName().split(".java")[0]);
				}
			}
		}

		return list;
	}

	// -------------------------------------------------------------------------
	public String getFileComment() {
		return fileComment;
	}

	public void setFileComment(String fileComment) {
		this.fileComment = fileComment;
	}

	public String getTypeComment() {
		return typeComment;
	}

	public void setTypeComment(String typeComment) {
		this.typeComment = typeComment;
	}

	public List<String> getPkgImports() {
		return pkgImports;
	}

	public void setPkgImports(List<String> pkgImports) {
		this.pkgImports = pkgImports;
	}

	public String getTargetPackage() {
		return targetPackage;
	}

	public void setTargetPackage(String targetPackage) {
		this.targetPackage = targetPackage;
	}

	public String getTargetPath() {
		return targetPath;
	}

	public void setTargetPath(String targetPath) {
		this.targetPath = targetPath;
		targetPathCheck(targetPath);
	}

	public String getSourcePath() {
		return sourcePath;
	}

	public void setSourcePath(String sourcePath) {
		this.sourcePath = sourcePath;
	}

	public String getSourcePackage() {
		return sourcePackage;
	}

	public void setSourcePackage(String sourcePackage) {
		this.sourcePackage = sourcePackage;
	}

	public boolean isOverWrite() {
		return overWrite;
	}

	public void setOverWrite(boolean overWrite) {
		this.overWrite = overWrite;
	}

	public int getSubStart() {
		return subStart;
	}

	public void setSubStart(int subStart) {
		this.subStart = subStart;
	}

}
